package com.kingmed.kmss.bpmn.flow.listener;

import com.kingmed.kmss.bpmn.flow.helper.ProcessHelper;
import com.kingmed.kmss.bpmn.modules.backup.model.BizApprovalStatus;
import com.kingmed.kmss.bpmn.modules.backup.model.BizApprovalTrail;
import com.kingmed.kmss.bpmn.modules.backup.service.BizApprovalStatusService;
import com.kingmed.kmss.bpmn.modules.backup.service.BizApprovalTrailService;
import com.kingmed.kmss.bpmn.flow.service.msg.BpmnMsgServiceImpl;
import com.kingmed.kmss.bpmn.flow.service.custom.ProcessStatusSyncServiceImpl;
import com.kingmed.kmss.bpmn.flow.utils.OrgUtils;
import com.kingmed.kmss.common.constant.bpmn.BpmnConstant;
import com.kingmed.kmss.common.constant.bpmn.ProcessConstant;
import com.kingmed.kmss.common.enums.bpmn.ProcessType;
import com.kingmed.kmss.common.utils.AppContextUtil;
import com.kingmed.kmss.framework.feign.client.admin.CommonAdminFeignServiceFacade;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.service.delegate.DelegateTask;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 流程审批追踪
 * @author wzg
 *
 *
 */
public class ApprovalTrailTaskListener implements TaskListener{

	/**
	 *
	 */
	private static final long serialVersionUID = -3036908590927665209L;

	BizApprovalTrailService trailSvc = AppContextUtil.getBean(BizApprovalTrailService.class);
	CommonAdminFeignServiceFacade remoteAdminSvc = AppContextUtil.getBean(CommonAdminFeignServiceFacade.class);
	ProcessStatusSyncServiceImpl procStatusSvc = AppContextUtil.getBean(ProcessStatusSyncServiceImpl.class);
	BizApprovalStatusService approvalStatusSvc = AppContextUtil.getBean(BizApprovalStatusService.class);

	ProcessHelper processHelper = AppContextUtil.getBean(ProcessHelper.class);
	BpmnMsgServiceImpl msgSvc = AppContextUtil.getBean(BpmnMsgServiceImpl.class);

	@Override
	public void notify(DelegateTask delegateTask) {
		saveApprovalStatus(delegateTask);
		saveApprovalTrail(delegateTask);
		syncStatus(delegateTask);

	}


	private void syncStatus(DelegateTask delegateTask) {
		Boolean approved = (Boolean) delegateTask.getVariable(BpmnConstant.VarKeys.APPROVED);
		String bizType = (String) delegateTask.getVariable(BpmnConstant.VarKeys.BIZ_TYPE);
		String bizTitle = (String) delegateTask.getVariable(BpmnConstant.VarKeys.BIZ_TITLE);
		String bizId = (String) delegateTask.getVariable(BpmnConstant.VarKeys.BIZ_ID);
		ProcessType processType = (ProcessType) delegateTask.getVariable(BpmnConstant.VarKeys.PROCESS_TYPE);
        String contractEndDate = (String) delegateTask.getVariable(BpmnConstant.VarKeys.CONTRACT_END_DATE);
        Map<String,Object> paramMap = new HashMap<>();
		paramMap.put(BpmnConstant.VarKeys.CONTRACT_END_DATE, contractEndDate);
		if (approved == null) {
			procStatusSvc.syncProcessStatus(bizType, bizId, bizTitle, ProcessConstant.Status.SUBMITTED, processType, paramMap);
		} else if (!approved) {
			String procInstId = delegateTask.getProcessInstanceId();
			procStatusSvc.syncProcessStatus(bizType, bizId, bizTitle, ProcessConstant.Status.REJECTED, processType, paramMap);
			msgSvc.send(bizType, bizId, null, null, procInstId);
		} else {
			// 流程结束由ProcessCompleteExecutionListener处理，这里认为是未结束
			procStatusSvc.syncProcessStatus(bizType, bizId, bizTitle, ProcessConstant.Status.APPROVING, processType, paramMap);
		}
	}

	private void saveApprovalTrail(DelegateTask delegateTask) {

		Boolean approved = (Boolean) delegateTask.getVariable(BpmnConstant.VarKeys.APPROVED);
		String approvedBy = delegateTask.getAssignee();
		String approvedDept = OrgUtils.getDeptByUser(approvedBy);
		String bizKey = (String) delegateTask.getVariable(BpmnConstant.VarKeys.BIZ_KEY );
		String bizType = (String) delegateTask.getVariable(BpmnConstant.VarKeys.BIZ_TYPE);
		String bizId = (String) delegateTask.getVariable(BpmnConstant.VarKeys.BIZ_ID);
		String comment = (String) delegateTask.getVariable(BpmnConstant.VarKeys.COMMENT);
		ProcessType processType = (ProcessType) delegateTask.getVariable(BpmnConstant.VarKeys.PROCESS_TYPE);

		String approvedByName = getApproverRealname(approvedBy);

		String procInstId = delegateTask.getProcessInstanceId();

		BizApprovalTrail trail = new BizApprovalTrail();
		trail.setApprovalResult(getApprovalResultDesc(approved));
		trail.setApprovedByName(approvedByName);
		trail.setApprovedBy(approvedBy);
		trail.setApproverDept(approvedDept);
		trail.setBizKey(bizKey);
		trail.setBizType(bizType);
		trail.setBusinessId(bizId);
		trail.setComment(comment);
		trail.setProcInstId(procInstId);
		trail.setApproveTime(new Date());
		trail.setProcessType(processType.getCode());
		trailSvc.saveApprovalTrail(trail);
	}

	private void saveApprovalStatus(DelegateTask delegateTask) {

		Boolean approved = (Boolean) delegateTask.getVariable(BpmnConstant.VarKeys.APPROVED);

		String bizKey = (String) delegateTask.getVariable(BpmnConstant.VarKeys.BIZ_KEY );
		String bizType = (String) delegateTask.getVariable(BpmnConstant.VarKeys.BIZ_TYPE);
		String bizId = (String) delegateTask.getVariable(BpmnConstant.VarKeys.BIZ_ID);
		String bizTitle = processHelper.getProcessVariable(delegateTask.getExecutionId(), BpmnConstant.VarKeys.BIZ_TITLE);
		String assignee = delegateTask.getAssignee();

		String procInstId = delegateTask.getProcessInstanceId();
		String requestedBy = "";
	//	String requestedByDept = "";
		Date requestTime = null;
		ProcessInstance procInst = processHelper.getProcessInstance(procInstId);
		if (procInst != null) {
			requestedBy = procInst.getStartUserId();
		//	requestedByDept = OrgUtils.getDeptByUser(requestedBy);
			requestTime = procInst.getStartTime();
		}

		int proccessStatus = calcProcessStatus(approved);
		BizApprovalStatus status = new BizApprovalStatus();
		status.setBizKey(bizKey);
		status.setBizType(bizType);
		status.setBusinessId(bizId);
		status.setBusinessTitle(bizTitle);
		status.setNextApprover("");
		//status.setNextApproverDept("");
		status.setCurrStatus(proccessStatus);

		status.setProcInstId(procInstId);
		status.setRequestBy(requestedBy);
		//status.setRequestByDept(requestedByDept);
		status.setRequestTime(requestTime);
		status.setApprovedBy(assignee);

		approvalStatusSvc.saveApprovalStatus(status);
	}

	private int calcProcessStatus(Boolean approved) {
		int status = ProcessConstant.Status.SUBMITTED;

		if (approved == null) {
			return status;
		} else if (!approved) {
			status = ProcessConstant.Status.REJECTED;
		} else {
			status = ProcessConstant.Status.APPROVING;
		}

		return status;
	}

	private String getApproverRealname(String approvedBy) {
		return remoteAdminSvc.getUserRealName(approvedBy);
	}

	private String getApprovalResultDesc(Boolean approved) {
		if (approved == null) {
			return BpmnConstant.ApprovalResult.SUBMIT;
		}
		return approved? BpmnConstant.ApprovalResult.APPROVED: BpmnConstant.ApprovalResult.REJECTED;
	}


}
